using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;

namespace Digitalmes.AvaloniaUI.Behaviors.DragAndDrop;

/// <summary>
/// 可拖拽的 Canvas。
/// </summary>
public sealed class DragDrawCanvas(Canvas canvas)
{
    const string ShapeType = "ShapeType";

    /// <summary>
    /// 图形选中事件。
    /// </summary>
    public Action<DraggableControl?>? OnShapeSelected;

    /// <summary>
    /// 启用交互性操作。
    /// </summary>
    public void EnableInteractions()
    {
        // 手动订阅 DragOver 和 Drop 事件
        canvas.AddHandler(DragDrop.DragOverEvent, OnCanvasDragOver, handledEventsToo: true);
        canvas.AddHandler(DragDrop.DropEvent, OnCanvasDrop, handledEventsToo: true);

        canvas.PointerPressed += (s, e) =>
        {
            OnShapeSelected?.Invoke(null);
        };
    }

    /// <summary>
    /// 图形拖拽事件
    /// </summary>
    public static async Task OnDragDrop(object? sender, PointerPressedEventArgs e)
    {
        if (sender is Control { Tag: string shapeType })
        {
            var data = new DataObject();
            data.Set(ShapeType, shapeType);
            // 启动拖拽操作
            await DragDrop.DoDragDrop(e, data, DragDropEffects.Copy);
        }
    }

    // Canvas 上拖动经过
    private void OnCanvasDragOver(object? sender, DragEventArgs e)
    {
        e.DragEffects = e.Data.Contains(ShapeType) ? DragDropEffects.Copy : DragDropEffects.None;

        e.Handled = true;
    }

    // 放置控件到 Canvas
    private void OnCanvasDrop(object? sender, DragEventArgs e)
    {
        if (e.Data.Contains(ShapeType))
        {
            var shapeType = e.Data.Get(ShapeType) as string;
            var position = e.GetPosition(canvas);

            DraggableControl? shape = shapeType switch
            {
                "Rectangle" => CreateRectangle(position),
                "Line" => CreateLine(position),
                _ => null
            };

            if (shape != null)
            {
                // 添加到 Canvas
                canvas.Children.Add(shape);
            }
        }

        e.Handled = true;
    }

    private DraggableRectangle CreateRectangle(Point position)
    {
        var control = new DraggableRectangle(position, canvas);
        control.EnableContextMenu();
        control.PointerPressed += (s, e) =>
        {
            OnShapeSelected?.Invoke((DraggableRectangle?)s);
        };
        return control;
    }

    private DraggableLine CreateLine(Point position)
    {
        var control = new DraggableLine(position, canvas);
        control.EnableContextMenu();
        return control;
    }
}
